Desbloqueie o poder da Federação GraphQL com Schema Stitching. Aprenda a construir uma API GraphQL unificada a partir de múltiplos serviços, melhorando a escalabilidade e a manutenibilidade.
Federação GraphQL: Schema Stitching - Um Guia Completo
No cenário em constante evolução do desenvolvimento de aplicações modernas, a necessidade de arquiteturas escaláveis e de fácil manutenção tornou-se primordial. Os microsserviços, com a sua modularidade inerente e capacidade de implementação independente, surgiram como uma solução popular. No entanto, gerir inúmeros microsserviços pode introduzir complexidades, especialmente quando se trata de expor uma API unificada para aplicações cliente. É aqui que a Federação GraphQL, e especificamente o Schema Stitching, entra em jogo.
O que é a Federação GraphQL?
A Federação GraphQL é uma arquitetura poderosa que lhe permite construir uma única API GraphQL unificada a partir de múltiplos serviços GraphQL subjacentes (frequentemente representando microsserviços). Permite que os desenvolvedores consultem dados em diferentes serviços como se fossem um único grafo, simplificando a experiência do cliente e reduzindo a necessidade de lógicas de orquestração complexas do lado do cliente.
Existem duas abordagens principais para a Federação GraphQL:
- Schema Stitching: Isto envolve a combinação de múltiplos esquemas GraphQL num único esquema unificado na camada de gateway. É uma abordagem mais antiga e depende de bibliotecas para gerir a combinação de esquemas e a delegação de consultas.
- Apollo Federation: Esta é uma abordagem mais recente e robusta que utiliza uma linguagem de esquema declarativa e um planeador de consultas dedicado para gerir o processo de federação. Oferece funcionalidades avançadas como extensões de tipo, diretivas de chave e rastreamento distribuído.
Este artigo foca-se no Schema Stitching, explorando os seus conceitos, benefícios, limitações e implementação prática.
Compreendendo o Schema Stitching
Schema Stitching é o processo de fundir múltiplos esquemas GraphQL num único esquema coeso. Este esquema unificado atua como uma fachada, escondendo a complexidade dos serviços subjacentes do cliente. Quando um cliente faz um pedido ao esquema unificado, o gateway encaminha inteligentemente o pedido para o(s) serviço(s) subjacente(s) apropriado(s), recupera os dados e combina os resultados antes de os devolver ao cliente.
Pense nisto da seguinte forma: Você tem vários restaurantes (serviços), cada um especializado em diferentes cozinhas. O Schema Stitching é como um menu universal que combina todos os pratos de cada restaurante. Quando um cliente faz um pedido a partir do menu universal, o pedido é encaminhado de forma inteligente para as cozinhas dos restaurantes apropriados, a comida é preparada e, em seguida, combinada numa única entrega para o cliente.
Conceitos Chave no Schema Stitching
- Esquemas Remotos: Estes são os esquemas GraphQL individuais de cada serviço subjacente. Cada serviço expõe o seu próprio esquema, que define os dados e as operações que fornece.
- Gateway: O gateway é o componente central responsável por unificar os esquemas remotos e expor o esquema unificado ao cliente. Ele recebe os pedidos do cliente, encaminha-os para os serviços apropriados e combina os resultados.
- Fusão de Esquemas: Este é o processo de combinar os esquemas remotos num único esquema. Isto envolve frequentemente renomear tipos e campos para evitar conflitos e definir relações entre tipos em diferentes esquemas.
- Delegação de Consultas: Quando um cliente faz um pedido ao esquema unificado, o gateway precisa de delegar o pedido ao(s) serviço(s) subjacente(s) apropriado(s) para recuperar os dados. Isto envolve traduzir a consulta do cliente para uma consulta que possa ser compreendida pelo serviço remoto.
- Agregação de Resultados: Depois de o gateway ter recuperado dados dos serviços subjacentes, ele precisa de combinar os resultados numa única resposta que possa ser devolvida ao cliente. Isto envolve frequentemente transformar os dados para corresponder à estrutura do esquema unificado.
Benefícios do Schema Stitching
O Schema Stitching oferece vários benefícios convincentes para organizações que adotam uma arquitetura de microsserviços:
- API Unificada: Fornece uma API única e consistente para os clientes, simplificando o acesso aos dados e reduzindo a necessidade de os clientes interagirem diretamente com múltiplos serviços. Isto resulta numa experiência de desenvolvedor mais limpa e intuitiva.
- Complexidade Reduzida no Cliente: Os clientes só precisam de interagir com o esquema unificado, protegendo-os das complexidades da arquitetura de microsserviços subjacente. Isto simplifica o desenvolvimento do lado do cliente e reduz a quantidade de código necessária no cliente.
- Escalabilidade Aumentada: Permite-lhe escalar serviços individuais de forma independente com base nas suas necessidades específicas. Isto melhora a escalabilidade geral e a resiliência do sistema. Por exemplo, um serviço de utilizador que está a experienciar uma carga elevada pode ser escalado sem afetar outros serviços como o catálogo de produtos.
- Manutenibilidade Melhorada: Promove a modularidade e a separação de responsabilidades, tornando mais fácil manter e evoluir serviços individuais. As alterações a um serviço têm menos probabilidade de impactar outros serviços.
- Adoção Gradual: Pode ser implementado de forma incremental, permitindo-lhe migrar gradualmente de uma arquitetura monolítica para uma arquitetura de microsserviços. Pode começar por unificar APIs existentes e depois decompor gradualmente o monólito em serviços mais pequenos.
Limitações do Schema Stitching
Embora o Schema Stitching ofereça inúmeras vantagens, é importante estar ciente das suas limitações:
- Complexidade: Implementar e gerir a unificação de esquemas pode ser complexo, especialmente em sistemas grandes e complexos. Um planeamento e design cuidadosos são essenciais.
- Sobrecarga de Desempenho: O gateway introduz alguma sobrecarga de desempenho devido à camada extra de indireção e à necessidade de delegar consultas e agregar resultados. A otimização cuidadosa é crucial para minimizar esta sobrecarga.
- Conflitos de Esquema: Podem surgir conflitos ao fundir esquemas de diferentes serviços, especialmente se usarem os mesmos nomes de tipos ou campos. Isto requer um design de esquema cuidadoso e, potencialmente, a renomeação de tipos e campos.
- Funcionalidades Avançadas Limitadas: Comparado com a Apollo Federation, o Schema Stitching carece de algumas funcionalidades avançadas como extensões de tipo e diretivas de chave, o que pode tornar mais desafiador gerir relações entre tipos em diferentes esquemas.
- Maturidade das Ferramentas: As ferramentas e o ecossistema em torno do Schema Stitching não são tão maduros como os da Apollo Federation. Isto pode tornar mais desafiador depurar e resolver problemas.
Implementação Prática do Schema Stitching
Vamos percorrer um exemplo simplificado de como implementar o Schema Stitching usando Node.js e a biblioteca graphql-tools
(uma escolha popular para a unificação de esquemas). Este exemplo envolve dois microsserviços: um Serviço de Utilizador e um Serviço de Produto.
1. Definir os Esquemas Remotos
Primeiro, defina os esquemas GraphQL para cada um dos serviços remotos.
Serviço de Utilizador (user-service.js
):
const { buildSchema } = require('graphql');
const userSchema = buildSchema(`
type User {
id: ID!
name: String
email: String
}
type Query {
user(id: ID!): User
}
`);
const users = [
{ id: '1', name: 'Alice Smith', email: 'alice@example.com' },
{ id: '2', name: 'Bob Johnson', email: 'bob@example.com' },
];
const userRoot = {
user: (args) => users.find(user => user.id === args.id),
};
module.exports = {
schema: userSchema,
rootValue: userRoot,
};
Serviço de Produto (product-service.js
):
const { buildSchema } = require('graphql');
const productSchema = buildSchema(`
type Product {
id: ID!
name: String
price: Float
userId: ID! # Foreign key to User Service
}
type Query {
product(id: ID!): Product
}
`);
const products = [
{ id: '101', name: 'Laptop', price: 1200, userId: '1' },
{ id: '102', name: 'Smartphone', price: 800, userId: '2' },
];
const productRoot = {
product: (args) => products.find(product => product.id === args.id),
};
module.exports = {
schema: productSchema,
rootValue: productRoot,
};
2. Criar o Serviço de Gateway
Agora, crie o serviço de gateway que irá unificar os dois esquemas.
Serviço de Gateway (gateway.js
):
const { stitchSchemas } = require('@graphql-tools/stitch');
const { makeRemoteExecutableSchema } = require('@graphql-tools/wrap');
const { graphqlHTTP } = require('express-graphql');
const express = require('express');
const { introspectSchema } = require('@graphql-tools/wrap');
const { printSchema } = require('graphql');
const fetch = require('node-fetch');
async function createRemoteSchema(uri) {
const fetcher = async (params) => {
const response = await fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});
return response.json();
};
const schema = await introspectSchema(fetcher);
return makeRemoteExecutableSchema({
schema,
fetcher,
});
}
async function main() {
const userSchema = await createRemoteSchema('http://localhost:4001/graphql');
const productSchema = await createRemoteSchema('http://localhost:4002/graphql');
const stitchedSchema = stitchSchemas({
subschemas: [
{ schema: userSchema },
{ schema: productSchema },
],
typeDefs: `
extend type Product {
user: User
}
`,
resolvers: {
Product: {
user: {
selectionSet: `{ userId }`,
resolve(product, args, context, info) {
return info.mergeInfo.delegateToSchema({
schema: userSchema,
operation: 'query',
fieldName: 'user',
args: {
id: product.userId,
},
context,
info,
});
},
},
},
},
});
const app = express();
app.use('/graphql', graphqlHTTP({
schema: stitchedSchema,
graphiql: true,
}));
app.listen(4000, () => console.log('Gateway server running on http://localhost:4000/graphql'));
}
main().catch(console.error);
3. Executar os Serviços
Terá de executar o Serviço de Utilizador e o Serviço de Produto em portas diferentes. Por exemplo:
Serviço de Utilizador (porta 4001):
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./user-service');
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: rootValue,
graphiql: true,
}));
app.listen(4001, () => console.log('User service running on http://localhost:4001/graphql'));
Serviço de Produto (porta 4002):
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { schema, rootValue } = require('./product-service');
const app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: rootValue,
graphiql: true,
}));
app.listen(4002, () => console.log('Product service running on http://localhost:4002/graphql'));
4. Consultar o Esquema Unificado
Agora pode consultar o esquema unificado através do gateway (a executar na porta 4000). Pode executar uma consulta como esta:
query {
product(id: "101") {
id
name
price
user {
id
name
email
}
}
}
Esta consulta recupera o produto com o ID "101" e também busca o utilizador associado do Serviço de Utilizador, demonstrando como o Schema Stitching lhe permite consultar dados de múltiplos serviços num único pedido.
Técnicas Avançadas de Schema Stitching
Além do exemplo básico, aqui estão algumas técnicas avançadas que podem ser usadas para melhorar a sua implementação de Schema Stitching:
- Delegação de Esquema: Isto permite-lhe delegar partes de uma consulta a diferentes serviços com base nos dados que estão a ser solicitados. Por exemplo, pode delegar a resolução de um tipo `User` ao Serviço de Utilizador e a resolução de um tipo `Product` ao Serviço de Produto.
- Transformação de Esquema: Isto envolve a modificação do esquema de um serviço remoto antes de ser unificado no esquema geral. Isto pode ser útil para renomear tipos e campos, adicionar novos campos ou remover campos existentes.
- Resolvers Personalizados: Pode definir resolvers personalizados no gateway para lidar com transformações de dados complexas ou para buscar dados de múltiplos serviços e combiná-los num único resultado.
- Partilha de Contexto: É frequentemente necessário partilhar informações de contexto entre o gateway e os serviços remotos, como tokens de autenticação ou IDs de utilizador. Isto pode ser alcançado passando informações de contexto como parte do processo de delegação de consulta.
- Tratamento de Erros: Implemente um tratamento de erros robusto para lidar graciosamente com erros que ocorrem nos serviços remotos. Isto pode envolver o registo de erros, o retorno de mensagens de erro amigáveis para o utilizador ou a nova tentativa de pedidos falhados.
Escolher entre Schema Stitching e Apollo Federation
Embora o Schema Stitching seja uma opção viável para a Federação GraphQL, a Apollo Federation tornou-se a escolha mais popular devido às suas funcionalidades avançadas e melhor experiência de desenvolvedor. Aqui está uma comparação das duas abordagens:
Funcionalidade | Schema Stitching | Apollo Federation |
---|---|---|
Definição do Esquema | Usa a linguagem de esquema GraphQL existente | Usa uma linguagem de esquema declarativa com diretivas |
Planeamento de Consultas | Requer delegação manual de consultas | Planeamento automático de consultas pelo Apollo Gateway |
Extensões de Tipo | Suporte limitado | Suporte nativo para extensões de tipo |
Diretivas de Chave | Não suportado | Usa a diretiva @key para identificar entidades |
Rastreamento Distribuído | Requer implementação manual | Suporte nativo para rastreamento distribuído |
Ferramentas e Ecossistema | Ferramentas menos maduras | Ferramentas mais maduras e uma grande comunidade |
Complexidade | Pode ser complexo de gerir em sistemas grandes | Projetado para sistemas grandes e complexos |
Quando escolher o Schema Stitching:
- Já tem serviços GraphQL existentes e quer combiná-los rapidamente.
- Precisa de uma solução de federação simples и não requer funcionalidades avançadas.
- Tem recursos limitados e quer evitar a sobrecarga de configurar a Apollo Federation.
Quando escolher a Apollo Federation:
- Está a construir um sistema grande e complexo com múltiplas equipas e serviços.
- Precisa de funcionalidades avançadas como extensões de tipo, diretivas de chave e rastreamento distribuído.
- Quer uma solução de federação mais robusta e escalável.
- Prefere uma abordagem mais declarativa e automatizada para a federação.
Exemplos do Mundo Real e Casos de Uso
Aqui estão alguns exemplos do mundo real de como a Federação GraphQL, incluindo o Schema Stitching, pode ser usada:
- Plataforma de E-commerce: Uma plataforma de e-commerce pode usar a Federação GraphQL para combinar dados de múltiplos serviços, como um serviço de catálogo de produtos, um serviço de utilizador, um serviço de pedidos e um serviço de pagamento. Isto permite que os clientes recuperem facilmente toda a informação de que precisam para exibir detalhes de produtos, perfis de utilizador, histórico de pedidos e informações de pagamento.
- Plataforma de Redes Sociais: Uma plataforma de redes sociais poderia usar a Federação GraphQL para combinar dados de serviços que gerem perfis de utilizador, publicações, comentários e 'gostos'. Isto permite que os clientes busquem eficientemente toda a informação necessária para exibir o perfil de um utilizador, as suas publicações e os comentários e 'gostos' associados a essas publicações.
- Aplicação de Serviços Financeiros: Uma aplicação de serviços financeiros pode usar a Federação GraphQL para combinar dados de serviços que gerem contas, transações e investimentos. Isto permite que os clientes recuperem facilmente toda a informação de que precisam para exibir saldos de contas, histórico de transações e portfólios de investimento.
- Sistema de Gestão de Conteúdo (CMS): Um CMS pode aproveitar a Federação GraphQL para integrar dados de várias fontes como artigos, imagens, vídeos e conteúdo gerado pelo utilizador. Isto permite uma API unificada para buscar todo o conteúdo relacionado a um tópico ou autor específico.
- Aplicação de Cuidados de Saúde: Integrar dados de pacientes de diferentes sistemas como registos de saúde eletrónicos (RSE), resultados de laboratório e agendamento de consultas. Isto oferece aos médicos um único ponto de acesso a informações abrangentes do paciente.
Melhores Práticas para o Schema Stitching
Para garantir uma implementação bem-sucedida do Schema Stitching, siga estas melhores práticas:
- Planeie o seu Esquema Cuidadosamente: Antes de começar a unificar esquemas, planeie cuidadosamente a estrutura do esquema unificado. Isto inclui definir as relações entre tipos em diferentes esquemas, renomear tipos e campos para evitar conflitos e considerar os padrões gerais de acesso a dados.
- Use Convenções de Nomenclatura Consistentes: Adote convenções de nomenclatura consistentes para tipos, campos e operações em todos os serviços. Isto ajudará a evitar conflitos e a facilitar a compreensão do esquema unificado.
- Documente o seu Esquema: Documente o esquema unificado de forma completa, incluindo descrições de tipos, campos e operações. Isto tornará mais fácil para os desenvolvedores entender e usar o esquema.
- Monitorize o Desempenho: Monitorize o desempenho do gateway и dos serviços remotos para identificar e resolver quaisquer gargalos de desempenho. Use ferramentas como o rastreamento distribuído para acompanhar os pedidos em múltiplos serviços.
- Implemente Segurança: Implemente medidas de segurança apropriadas para proteger o gateway e os serviços remotos contra acesso não autorizado. Isto pode envolver o uso de mecanismos de autenticação e autorização, bem como validação de entrada e codificação de saída.
- Versione o seu Esquema: À medida que evolui os seus esquemas, versione-os adequadamente para garantir que os clientes possam continuar a usar versões mais antigas do esquema sem quebras. Isto ajudará a evitar alterações que quebrem a compatibilidade e a garantir a retrocompatibilidade.
- Automatize a Implantação: Automatize a implantação do gateway e dos serviços remotos para garantir que as alterações possam ser implementadas de forma rápida e confiável. Isto ajudará a reduzir o risco de erros e a melhorar a agilidade geral do sistema.
Conclusão
A Federação GraphQL com Schema Stitching oferece uma abordagem poderosa para construir APIs unificadas a partir de múltiplos serviços numa arquitetura de microsserviços. Ao compreender os seus conceitos centrais, benefícios, limitações e técnicas de implementação, pode aproveitar o Schema Stitching para simplificar o acesso a dados, melhorar a escalabilidade e aumentar a manutenibilidade. Embora a Apollo Federation tenha surgido como uma solução mais avançada, o Schema Stitching permanece uma opção viável para cenários mais simples ou ao integrar serviços GraphQL existentes. Considere cuidadosamente as suas necessidades e requisitos específicos para escolher a melhor abordagem para a sua organização.